/*
 * IndexadorTwit.cpp

 *      Author: carlos
 */

#include "IndexadorTwit.h"
#include "../EntityFactory.h"
IndexadorTwit::IndexadorTwit(HashExtensible* hash,
		IStrutureBTreeImpl* indiceFechaAsc, IStrutureBTreeImpl* indiceFechaDesc,
		IStrutureBTreeImpl* indiceAutor) {

	this->hash = hash;
	this->indiceAutor = indiceAutor;
	this->indiceFechaAsc = indiceFechaAsc;
	this->indiceFechaDesc = indiceFechaDesc;
}

void IndexadorTwit::add(Twit* twit) {
	Fecha* fecha = twit->geFecha();
	SimpleSecondaryIndex* sIndex =
			(SimpleSecondaryIndex*) this->indiceFechaAsc->find(
					fecha->getFechaFormateada());
	if (sIndex == NULL) {
		sIndex = EntityFactory::createSimpleSecondaryIndex(FECHAASC_IDTWEET);
		sIndex->setID(StringUtils::stringToId(fecha->getFechaFormateada()));
		sIndex->agregarIdOrdenado(twit->getId());
		this->indiceFechaAsc->insert(sIndex);
	} else {
		sIndex->agregarIdOrdenado(twit->getId());
		this->indiceFechaAsc->modify(sIndex);
	}
	delete sIndex;

	SimpleStringSecondaryindex* ssIndex =
			(SimpleStringSecondaryindex*) this->indiceAutor->find(
					twit->getAutor());
	if (ssIndex == NULL) {
		ssIndex = EntityFactory::createSimpleStringSecondaryIndex(
				TITULO_IDTWEET);
		ssIndex->setIdstring(twit->getAutor());
		ssIndex->agregarIdOrdenado(twit->getId());
		this->indiceAutor->insert(ssIndex);
	} else {
		ssIndex->agregarIdOrdenado(twit->getId());
		this->indiceAutor->modify(ssIndex);
	}
	delete ssIndex;

}

void IndexadorTwit::deleteRecord(int id) {
	cout << "Eliminado registro id: " << id << endl;
	Twit* twit = new Twit();
	twit->setId(id);
	Twit* twitRecoverd = this->hash->searchTwit(twit);
	if (twitRecoverd != NULL) {
		this->hash->doHashingDelete(twitRecoverd);
		SimpleSecondaryIndex* sIndex =
				(SimpleSecondaryIndex*) this->indiceFechaAsc->find(
						twitRecoverd->geFecha()->getFechaFormateada());
		if (sIndex != NULL) {
			sIndex->removerIdRelacional(id);
			this->indiceFechaAsc->modify(sIndex);
			if (sIndex->getId_relacionales().size() == 0) {
				this->indiceFechaAsc->remove(
						StringUtils::intToString(sIndex->getID()));
			}
		} else {
			cout << "Error en la logica de indexacion. El id: " << id
					<< " deberia estar indexado por fecha";
		}
		delete sIndex;
		SimpleStringSecondaryindex* ssIndex =
				(SimpleStringSecondaryindex*) this->indiceAutor->find(
						twitRecoverd->getAutor());
		if (ssIndex != NULL) {
			ssIndex->removerIdRelacional(id);
			this->indiceAutor->modify(ssIndex);
			if (ssIndex->getId_relacionales().size() == 0) {
				this->indiceAutor->remove(ssIndex->getIdstring());
			}
		} else {
			cout << "Error en la logica de indexacion. El id: " << id
					<< " deberia estar indexado por fecha";
		}
	}else{
		cout<<"No se encontro el twit por id: "<<id<<endl;
	}

}

/**
 * Eliminamos todos los twits con esa fecha exacta
 */
void IndexadorTwit::deleteRecordFechaExacta(int aniomesdia) {
	//recupero los twits de la fecha y elimino los id de cada uno

	SimpleSecondaryIndex* ientidad =
			(SimpleSecondaryIndex*) this->indiceFechaAsc->find(
					StringUtils::intToString(aniomesdia));
	if (ientidad != NULL) {
		vector<ID> idsAEliminar = ientidad->getId_relacionales();
		vector<ID>::iterator itIdsAEliminar = idsAEliminar.begin();
		while (itIdsAEliminar != idsAEliminar.end()) {
			this->deleteRecord((*itIdsAEliminar));
			itIdsAEliminar++;
		}
	} else {
		cout << "No existen twits para la fecha: " << aniomesdia << endl;
	}

}

/**
 * Buscamos todos los twits con esa fecha aproximada y los eliminamos
 */
void IndexadorTwit::deleteRecordMayorFecha(int fecha) {
	SimpleSecondaryIndex* ientidad =
			(SimpleSecondaryIndex*) this->indiceFechaAsc->findAproximado(
					StringUtils::intToString(fecha));
	vector<SimpleSecondaryIndex*> elementosIndiceAEliminar;
	while (ientidad != NULL) {
		//como es una busqueda aproximada tengo que verificar que realmente corresponde elminarlo.
		if ((int)ientidad->getID() > fecha) {
			cout << "Eliminado elementos: " << ientidad->toString() << endl;
			elementosIndiceAEliminar.push_back(ientidad);
		}

		ientidad = (SimpleSecondaryIndex*) this->indiceFechaAsc->siguiente();

	}

	//Ahora acumulo todos los ids asi
	vector<ID> idsAElminar;
	vector<SimpleSecondaryIndex*>::iterator itElementosIndiceAEliminar =
			elementosIndiceAEliminar.begin();
	while (itElementosIndiceAEliminar != elementosIndiceAEliminar.end()) {
		vector<ID> ids = (*itElementosIndiceAEliminar)->getId_relacionales();
		for (vector<ID>::iterator it = ids.begin(); it != ids.end(); it++) {
			idsAElminar.push_back((*it));
		}
		itElementosIndiceAEliminar++;
	}
	for (vector<ID>::iterator it = idsAElminar.begin(); it != idsAElminar.end();
			it++) {
		this->deleteRecord((*it));
	}
	itElementosIndiceAEliminar = elementosIndiceAEliminar.begin();
	while (itElementosIndiceAEliminar != elementosIndiceAEliminar.end()) {
		delete (*itElementosIndiceAEliminar);
		elementosIndiceAEliminar.erase(itElementosIndiceAEliminar);

	}
}

void IndexadorTwit::deleteRecordMenorFecha(int fecha) {

	SimpleSecondaryIndex* ientidad =
				(SimpleSecondaryIndex*) this->indiceFechaAsc->findAproximado(
						StringUtils::intToString(fecha));
		vector<SimpleSecondaryIndex*> elementosIndiceAEliminar;
		while (ientidad != NULL) {
			//como es una busqueda aproximada tengo que verificar que realmente corresponde elminarlo.
			if ((int)ientidad->getID() < fecha) {
				cout << "Eliminado elementos: " << ientidad->toString() << endl;
				elementosIndiceAEliminar.push_back(ientidad);
			}

			ientidad = (SimpleSecondaryIndex*) this->indiceFechaAsc->anterior();

		}

		//Ahora acumulo todos los ids asi
		vector<ID> idsAElminar;
		vector<SimpleSecondaryIndex*>::iterator itElementosIndiceAEliminar =
				elementosIndiceAEliminar.begin();
		while (itElementosIndiceAEliminar != elementosIndiceAEliminar.end()) {
			vector<ID> ids = (*itElementosIndiceAEliminar)->getId_relacionales();
			for (vector<ID>::iterator it = ids.begin(); it != ids.end(); it++) {
				idsAElminar.push_back((*it));
			}
			itElementosIndiceAEliminar++;
		}
		for (vector<ID>::iterator it = idsAElminar.begin(); it != idsAElminar.end();
				it++) {
			this->deleteRecord((*it));
		}
		itElementosIndiceAEliminar = elementosIndiceAEliminar.begin();
		while (itElementosIndiceAEliminar != elementosIndiceAEliminar.end()) {
			delete (*itElementosIndiceAEliminar);
			elementosIndiceAEliminar.erase(itElementosIndiceAEliminar);

		}
}

void IndexadorTwit::exportar() {
	this->indiceAutor->exportar();
	cout<<endl<<endl<<endl;
	this->indiceFechaAsc->exportar();
}

/**
 * Borramos todos la entidad que relaciona un indice y todos sus elementos indexados
 */
void IndexadorTwit::eliminarSimpleSecondayIndex(SimpleSecondaryIndex* ientidad,
		int aniomesdia) {
	if (ientidad != NULL) {
		vector<ID> idsRelacionales = ientidad->getId_relacionales();

		vector<ID>::iterator itIdsRelacionales;
		Twit twit;
		for (vector<ID>::iterator it = idsRelacionales.begin();
				it != idsRelacionales.end(); it++) {
			int idAElminar = (*it);

			twit.setId(idAElminar);

			/*Twit* twitRecuperado = this->hash->searchTwit(&twit);

			 this->hash->doHashingDelete(&twit);
			 //ahora hay que eliminar los id de autores. Por cada
			 SimpleStringSecondaryindex* ssIndex =
			 (SimpleStringSecondaryindex*) this->indiceAutor->find(
			 twit.getAutor());
			 if (ssIndex != NULL) {
			 ssIndex->removerIdRelacional(twitRecuperado->getId());
			 }
			 delete twitRecuperado;
			 }
			 delete twit;
			 this->indiceFechaAsc->remove(StringUtils::intToString(twit));*/
		}
	} else {
		cout << "No existen twtis para la fecha" << aniomesdia << endl;
	}

}

IndexadorTwit::~IndexadorTwit() {
}

